package com.openharmony.filepicker.utils;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadPoolUtil {

    private static volatile ThreadPoolExecutor executor;

    private static volatile boolean isPaused = false;
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition pauseCondition;
    private static LinkedBlockingDeque blockingQueue = new LinkedBlockingDeque();

    public static Executor threadPool() {
        synchronized (ThreadPoolUtil.class) {
            if (executor == null) {
                synchronized (ThreadPoolUtil.class) {
                    init();
                }
            }
        }
        return executor;
    }

    private static void init() {

        pauseCondition = lock.newCondition();

        int corePoolSize = 2;
        int maxPoolSize = 4;
        long keepAliveTime = 30;
        TimeUnit unit = TimeUnit.SECONDS;
        AtomicLong seq = new AtomicLong();

        ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable runnable) {
                Thread thread = new Thread(runnable);
                thread.setName("fishbun-executor-" + seq.getAndIncrement());
                return thread;
            }
        };

        executor = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveTime,
                unit,
                blockingQueue,
                threadFactory) {

            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                if (isPaused) {
                    lock.lock();
                    try {

                        pauseCondition.await();

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    } finally {

                        lock.unlock();

                    }
                }
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {

            }
        };
    }

    public static void execute(Runnable runnable) {
        threadPool().execute(runnable);
    }

    public static class PriorityRunnable implements Runnable, Comparable<PriorityRunnable> {

        int priority;
        Runnable runnable;

        public PriorityRunnable(int priority, Runnable runnable) {
            this.priority = priority;
            this.runnable = runnable;
        }

        @Override
        public void run() {
            runnable.run();
        }

        @Override
        public int compareTo(PriorityRunnable priorityRunnable) {
            if (this.priority < priorityRunnable.priority) {
                return 1;
            } else if (this.priority > priorityRunnable.priority) {
                return -1;
            }
            return 0;
        }
    }

    public static void pause() {
        lock.lock();
        try {
            isPaused = true;
        }finally {
            lock.unlock();
        }
    }

    public static void resume() {
        lock.lock();
        try {

            isPaused = false;
            pauseCondition.signalAll();

        } finally {

            lock.unlock();

        }
    }

    public static void clear() {
        blockingQueue.clear();
    }
}
